package com.example.reflection;

import com.example.reflection.entity.Person;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.util.Random;

/**
 * @author readpage
 * @create 2022-10-21 13:35
 * 通过发射创建对应的运行时类的对象
 */
public class NewInstanceTest {

    @Test
    public void test() throws InstantiationException, IllegalAccessException {
        Class<Person> clazz = Person.class;
        /**
         * newInstance(): 调用此方法，创建对应的运行时类的对象,内部类调用运行时空参的构造器
         * 要想此方法正常的创建运行时类的对象，要求:
         * 1.运行时类必须提供空参的构造器
         * 2.空参的构造器的访问权限得够。通常，设置为public。
         *
         * 在javabean要求提供一个public得空参构造器。原因:
         * 1.便于通过反射，创建运行时类得对象
         * 2.便于子类继承此运行类时，默认调用super()时，保证父类由此构造器
         */
        Person person = clazz.newInstance();
        System.out.println(person);
    }

    //反射的动态性
    @Test
    public void test2() {
        Object obj = null;
        for (int i = 0; i < 100; i++) {
            int num = new Random().nextInt(3);//0, 1, 2
            String classPath = "";
            switch (num) {
                case 0:
                    classPath = "java.util.Date";
                    break;
                case 1:
                    classPath = "java.lang.Object";
                    break;
                case 2:
                    classPath = "com.example.reflection.entity.Person";
                    break;
            }
            obj = getInstance(classPath);
            System.out.println(obj);
        }
    }

    /**
     * 创建一个指定类的对象
     * classPath: 指定类的全类名
     * @param classPath
     * @return
     */
    public Object getInstance(String classPath) {
        try {
            Class<?> clazz = Class.forName(classPath);
            return clazz.getDeclaredConstructor().newInstance();
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}
